use std::error::Error;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;
use chrono::{DateTime, Utc};
use log::{error, warn, info};
use std::collections::HashMap;

use super::processor::{DataValidator, DataCleaner};
use super::source::health_check::PerformanceMetrics;
use super::source::{
    DataSource, StockQuote, SectorIndex, MarketSentiment,
    VolumeDistribution, MarketBreadth, VolatilityIndex
};
use crate::config::data_source_config::DataSourceConfig;

pub struct MarketDataCollector {
    primary_source: Box<dyn DataSource>,
    backup_sources: Vec<Box<dyn DataSource>>,
    current_source: Arc<RwLock<usize>>,
    switch_back_delay: Duration,
    last_failure: Arc<RwLock<Option<DateTime<Utc>>>>,
    config: DataSourceConfig,
    performance_metrics: Arc<RwLock<HashMap<String, PerformanceMetrics>>>,
}

#[derive(Debug)]
pub enum DataCollectionError {
    SourceError(String),
    ValidationError(String),
    NoAvailableSource,
}

impl std::fmt::Display for DataCollectionError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            DataCollectionError::SourceError(msg) => write!(f, "Data source error: {}", msg),
            DataCollectionError::ValidationError(msg) => write!(f, "Data validation error: {}", msg),
            DataCollectionError::NoAvailableSource => write!(f, "No available data source"),
        }
    }
}

impl Error for DataCollectionError {}

impl MarketDataCollector {
    pub async fn get_primary_source(&self) -> Box<&dyn DataSource> {
        Box::new(&*self.primary_source)
    }

    pub async fn get_backup_sources(&self) -> Vec<Box<&dyn DataSource>> {
        self.backup_sources.iter()
            .map(|source| Box::new(&**source))
            .collect()
    }

    pub async fn get_performance_metrics(&self) -> HashMap<String, PerformanceMetrics> {
        self.performance_metrics.read().await.clone()
    }

    pub fn new(
        primary_source: Box<dyn DataSource>,
        backup_sources: Vec<Box<dyn DataSource>>,
        config: DataSourceConfig,
    ) -> Self {
        let mut metrics = HashMap::new();
        
        // 初始化性能指标
        metrics.insert(primary_source.name().to_string(), PerformanceMetrics {
            avg_response_time: Duration::from_secs(0),
            min_response_time: Duration::from_secs(u64::MAX),
            max_response_time: Duration::from_secs(0),
            request_count: 0,
            error_rate: 0.0,
            last_update: Utc::now(),
        });
        
        for source in &backup_sources {
            metrics.insert(source.name().to_string(), PerformanceMetrics {
                avg_response_time: Duration::from_secs(0),
                min_response_time: Duration::from_secs(u64::MAX),
                max_response_time: Duration::from_secs(0),
                request_count: 0,
                error_rate: 0.0,
                last_update: Utc::now(),
            });
        }
        
        Self {
            primary_source,
            backup_sources,
            current_source: Arc::new(RwLock::new(0)),
            switch_back_delay: Duration::from_secs(300), // 5分钟后尝试切回主数据源
            last_failure: Arc::new(RwLock::new(None)),
            config,
            performance_metrics: Arc::new(RwLock::new(metrics)),
        }
    }

    async fn get_current_source(&self) -> Box<&dyn DataSource> {
        let current_idx = *self.current_source.read().await;
        if current_idx == 0 {
            Box::new(&*self.primary_source)
        } else {
            Box::new(&*self.backup_sources[current_idx - 1])
        }
    }

    async fn switch_source(&self) -> Result<(), DataCollectionError> {
        let mut current_idx = self.current_source.write().await;
        let total_sources = self.backup_sources.len() + 1;
        
        // 如果当前是主数据源，切换到第一个备用源
        if *current_idx == 0 {
            if !self.backup_sources.is_empty() {
                *current_idx = 1;
                *self.last_failure.write().await = Some(Utc::now());
                info!("Switched to backup source: {}", self.backup_sources[0].name());
                return Ok(());
            }
        } else {
            // 如果当前是备用源，尝试切换到下一个备用源
            let next_idx = *current_idx + 1;
            if next_idx < total_sources {
                *current_idx = next_idx;
                info!("Switched to next backup source: {}", self.backup_sources[next_idx - 1].name());
                return Ok(());
            }
        }
        
        Err(DataCollectionError::NoAvailableSource)
    }

    async fn try_switch_back_to_primary(&self) -> bool {
        if let Some(last_failure) = *self.last_failure.read().await {
            let elapsed = Utc::now().signed_duration_since(last_failure);
            if elapsed.to_std().unwrap() >= self.switch_back_delay {
                let mut current_idx = self.current_source.write().await;
                *current_idx = 0;
                *self.last_failure.write().await = None;
                info!("Switched back to primary source: {}", self.primary_source.name());
                return true;
            }
        }
        false
    }

    async fn collect_with_retry<T, F>(&self, mut operation: F) -> Result<T, DataCollectionError>
    where
        T: DataValidator + DataCleaner,
        F: FnMut(&dyn DataSource) -> Result<T, Box<dyn Error + Send + Sync>>,
    {
        // 尝试切回主数据源
        self.try_switch_back_to_primary().await;

        let mut retries = 0;
        let max_retries = self.config.max_retries;

        loop {
            let source = self.get_current_source().await;
            let source_name = source.name().to_string();
            
            // 记录开始时间，用于性能监控
            let start_time = Instant::now();
            
            match operation(&**source) {
                Ok(mut data) => {
                    // 记录响应时间
                    let response_time = start_time.elapsed();
                    
                    // 更新性能指标
                    self.update_performance_metrics(&source_name, response_time, true).await;
                    
                    // 数据验证
                    if let Err(e) = data.validate() {
                        error!("Data validation error: {}", e);
                        return Err(DataCollectionError::ValidationError(e.to_string()));
                    }

                    // 数据清洗
                    data.clean();
                    return Ok(data);
                }
                Err(e) => {
                    // 记录响应时间
                    let response_time = start_time.elapsed();
                    
                    // 更新性能指标，标记为错误
                    self.update_performance_metrics(&source_name, response_time, false).await;
                    
                    error!("Data collection error from {}: {}", source_name, e);
                    retries += 1;

                    if retries >= max_retries {
                        // 切换到下一个数据源
                        if let Err(switch_err) = self.switch_source().await {
                            error!("Failed to switch data source: {}", switch_err);
                            return Err(switch_err);
                        }
                        retries = 0;
                    }

                    // 如果所有数据源都尝试过了，返回错误
                    if *self.current_source.read().await >= self.backup_sources.len() {
                        return Err(DataCollectionError::SourceError(e.to_string()));
                    }

                    // 等待一段时间后重试
                    tokio::time::sleep(Duration::from_secs(1)).await;
                }
            }
        }
    }
    
    async fn update_performance_metrics(&self, source_name: &str, response_time: Duration, success: bool) {
        let mut metrics = self.performance_metrics.write().await;
        
        if let Some(metric) = metrics.get_mut(source_name) {
            // 更新请求计数
            metric.request_count += 1;
            
            // 更新响应时间统计
            metric.avg_response_time = Duration::from_nanos(
                ((metric.avg_response_time.as_nanos() * (metric.request_count - 1) as u128) 
                + response_time.as_nanos()) / metric.request_count as u128 as u64
            );
            
            if response_time < metric.min_response_time {
                metric.min_response_time = response_time;
            }
            
            if response_time > metric.max_response_time {
                metric.max_response_time = response_time;
            }
            
            // 更新错误率
            if !success {
                metric.error_rate = (metric.error_rate * (metric.request_count - 1) as f64 + 1.0) 
                    / metric.request_count as f64;
            } else {
                metric.error_rate = (metric.error_rate * (metric.request_count - 1) as f64) 
                    / metric.request_count as f64;
            }
            
            metric.last_update = Utc::now();
        } else {
            // 如果没有找到对应的指标记录，创建一个新的
            metrics.insert(source_name.to_string(), PerformanceMetrics {
                avg_response_time: response_time,
                min_response_time: response_time,
                max_response_time: response_time,
                request_count: 1,
                error_rate: if success { 0.0 } else { 1.0 },
                last_update: Utc::now(),
            });
        }
    }

    pub async fn get_stock_quote(&self, symbol: &str) -> Result<StockQuote, DataCollectionError> {
        let symbol = symbol.to_string();
        self.collect_with_retry(|source| source.get_stock_quote(&symbol)).await
    }

    pub async fn get_sector_indices(&self) -> Result<Vec<SectorIndex>, DataCollectionError> {
        self.collect_with_retry(|source| source.get_sector_indices()).await
    }

    pub async fn get_market_sentiment(&self) -> Result<MarketSentiment, DataCollectionError> {
        self.collect_with_retry(|source| source.get_market_sentiment()).await
    }

    pub async fn get_volume_distribution(&self) -> Result<VolumeDistribution, DataCollectionError> {
        self.collect_with_retry(|source| source.get_volume_distribution()).await
    }

    pub async fn get_market_breadth(&self) -> Result<MarketBreadth, DataCollectionError> {
        self.collect_with_retry(|source| source.get_market_breadth()).await
    }

    pub async fn get_volatility_indices(&self) -> Result<Vec<VolatilityIndex>, DataCollectionError> {
        self.collect_with_retry(|source| source.get_volatility_indices()).await
    }
}